package com.cqndt.disaster.device.service.impl;

import com.cqndt.disaster.device.common.util.BinaryUtil;
import com.cqndt.disaster.device.common.util.IdUtil;
import com.cqndt.disaster.device.dao.DataCtccMapper;
import com.cqndt.disaster.device.dao.TabOrderLogMapper;
import com.cqndt.disaster.device.enums.CtccEnum;
import com.cqndt.disaster.device.service.DataCtccService;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

import static com.cqndt.disaster.device.common.util.BinaryUtil.sortHighShort;


/**
 * @Description: ctcc业务数据解析实现
 * @Auther: lhl
 * @Date: 2019/4/30 09:16
 */
@Service
@Slf4j
public class DataCtccServiceImpl implements DataCtccService {

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss'Z'");
    private static final DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    @Autowired
    private DataCtccMapper dataMappper;
    @Autowired
    private TabOrderLogMapper tabOrderLogMapper;
    /**
     * 解析指令数据
     *
     * @param body
     */
    @Override
    public void dataProcessing(String body) {

        JsonObject jsonData = new JsonParser().parse(body).getAsJsonObject();
        JsonObject service = jsonData.getAsJsonObject("service");
        JsonObject msg = service.getAsJsonObject("data");
        if (!msg.has("payload")) {
            return;
        }
        String value = BinaryUtil.bytesToHexFun3(Base64Utils.decode(msg.get("payload").getAsString().getBytes()));
        // 设备编号
        String deviceNo = jsonData.get("deviceId").getAsString();
        //时间
        String s = service.get("eventTime").getAsString();
        LocalDateTime parse = LocalDateTime.parse(s, formatter);
        LocalDateTime plus = parse.plus(8, ChronoUnit.HOURS);
        String date = formatter2.format(plus);
        //解析设备类型
        String deviceType = value.substring(10, 14).toLowerCase();
        String imei = value.substring(10, 26).toLowerCase();
        //数据
        String hexStr = value.substring(26);
        String headHex = hexStr.substring(0, 4);
        String headHexs = sortHighShort(headHex);
        List<List<String>> lists = null;
        switch (headHexs) {
            case "ab01":// 基础信息
                lists = parseCrack(deviceNo, hexStr);
                break;
            case "ab11": // 心跳包
                lists = parseHeartbeat(deviceNo, hexStr);
                break;
            case "ab03": // GPS
                lists = parseGPS(deviceNo, hexStr);
                break;
            case "ab04": // 角度偏移告警阈值
                lists = parseAngleOffset(deviceNo, hexStr);
                break;
            case "ab06":// 拉线偏移告警阈值
                lists = parseStayWireOffset(deviceNo, hexStr);
                break;
            case "ab0d": // 数据周期
                lists = parseDatePeriod(deviceNo, hexStr);
                break;
            case "ab0e": // 版本
                lists = parseVersion(deviceNo, hexStr);
                break;
            case "ab0f": // 采样间隔
                lists = parseSampleInterval(deviceNo, hexStr);
                break;
            default:
        }

        if (lists == null || lists.size() <= 0) {
            return;
        }
        Map<String, Object> map = new HashMap<>();

        map.put("at", date);
        map.put("devId", deviceNo);
        map.put("imei", imei);
        map.put("list", lists);
        dataMappper.saveAndList(map);

        if ("0f03".equals(deviceType)) {
            List<List<String>> listss = new ArrayList<>();
            listss.add(new ArrayList() {{
                add(IdUtil.getIncreaseIdByNanoTime());
                add(CtccEnum.DEVICE_TYPE.getCode());
                add("DLF");
            }});
            map.put("list", listss);
            dataMappper.saveAndList(map);
        }
    }

    /**
     * 采样间隔
     *
     * @param deviceNo
     * @param hexStr
     * @return
     */
    private List<List<String>> parseSampleInterval(String deviceNo, String hexStr) {
        List<List<String>> lists = new ArrayList<>();
        Integer val = Integer.parseInt(sortHighShort(hexStr.substring(10, 14)), 16);
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.SAMPLING_CYCLE.getCode());
            add(val);
        }});

        return lists;
    }

    /**
     * 数据周期
     *
     * @param deviceNo
     * @param hexStr
     * @return
     */
    private List<List<String>> parseDatePeriod(String deviceNo, String hexStr) {
        List<List<String>> lists = new ArrayList<>();
        //静止上报周期
        Integer staticPeriod = BinaryUtil.HexToInt(sortHighShort(hexStr.substring(16, 24)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.REPORING_CYCLE.getCode());
            add(staticPeriod);
        }});

        return lists;
    }

    /**
     * 软件版本
     *
     * @param deviceNo
     * @param hexStr
     * @return
     */
    private List<List<String>> parseVersion(String deviceNo, String hexStr) {
        List<List<String>> lists = new ArrayList<>();
        //软件版本
        String softwareVersionHexStr = hexStr.substring(8, 12);
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.SOFTWARE.getCode());
            add(softwareVersionHexStr);
        }});
        // 硬件版本
        String hardwareVersionHexStr = hexStr.substring(12, 14);
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.HARDWARE.getCode());
            add(hardwareVersionHexStr);
        }});

        return lists;
    }

    /**
     * 心跳包
     *
     * @param deviceNo
     * @param hexStr
     * @return
     */
    private List<List<String>> parseHeartbeat(String deviceNo, String hexStr) {
        List<List<String>> lists = new ArrayList<>();
        //信号 强度 整数，0-31表示-115到-53，99表示无信号
        Integer val = BinaryUtil.HexToInt(hexStr.substring(26, 28)) * 2 - 115;
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.SIGNAL.getCode());
            add(val);
        }});
        return lists;
    }

    /**
     * ab01 基础信息
     *
     * @param deviceNo 设备编号
     * @param hexStr   数据部分
     */
    private List<List<String>> parseCrack(String deviceNo, String hexStr) {
        List<List<String>> lists = new ArrayList<>();
        /* 振动强度(单位m/s^2)----时间 */
        Integer vibrationStrength = BinaryUtil.HexToInt(sortHighShort(hexStr.substring(36, 44)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.SHOCK_TIME.getCode());
            add(vibrationStrength);
        }});
        /*振动总次数(4B)----次数  */
        int vibrationTimesTotal = BinaryUtil.HexToInt(sortHighShort(hexStr.substring(44, 52)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.SHOCK_NUM.getCode());
            add(vibrationTimesTotal);
        }});
        /*本次振动次数(1B)----方向  */
        String vibrationTimes = BinaryUtil.hexStringToString(hexStr.substring(52, 54));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.SHOCK_DIRECTION.getCode());
            add(vibrationTimes);
        }});
        /*倾角度X(4B)  */
        Float dipX = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(54, 62)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.DIPANGLE_X.getCode());
            add(dipX);
        }});
        /*倾角度Y(4B)  */
        Float dipY = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(62, 70)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.DIPANGLE_Y.getCode());
            add(dipY);
        }});
        /*倾角度Z(4B)  */
        Float dipZ = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(70, 78)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.DIPANGLE_Z.getCode());
            add(dipZ);
        }});
        /*拉线长度*/
        Float pullLine = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(78, 86)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.PULLLINE.getCode());
            add(pullLine);
        }});
        /*电量*/
        int electricity = BinaryUtil.HexToInt(hexStr.substring(86, 88));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.ELECTRIIC.getCode());
            add(pullLine);
        }});
        /*电压*/
        Float voltage = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(88, 96)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.VOLTAGE.getCode());
            add(voltage);
        }});

        return lists;
    }


    /**
     * gps
     *
     * @param deviceNo 设备编号
     * @param hexStr   数据部分
     * @return
     */
    private List<List<String>> parseGPS(String deviceNo, String hexStr) {
        List<List<String>> lists = new ArrayList<>();
        //纬度
        Float latitude = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(44, 52)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.LATITUDE.getCode());
            add(latitude);
        }});
        // 经度
        Float longitude = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(36, 44)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.LONGITUDE.getCode());
            add(longitude);
        }});

        return lists;
    }

    /**
     * gps 角度偏移告警阈值
     *
     * @param deviceNo 设备编号
     * @param hexStr   数据部分
     * @return
     */
    private List<List<String>> parseAngleOffset(String deviceNo, String hexStr) {
        List<List<String>> lists = new ArrayList<>();
        Float threshold = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(8, 16)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.ANGLE_WARN.getCode());
            add(threshold);
        }});
        return lists;
    }

    /**
     * gps 拉线偏移告警阈值
     *
     * @param deviceNo 设备编号
     * @param hexStr   数据部分
     * @return
     */
    private List<List<String>> parseStayWireOffset(String deviceNo, String hexStr) {
        List<List<String>> lists = new ArrayList<>();
        Float threshold = BinaryUtil.strToFloat(sortHighShort(hexStr.substring(8, 16)));
        lists.add(new ArrayList() {{
            add(IdUtil.getIncreaseIdByNanoTime());
            add(CtccEnum.ANGLE_WARN.getCode());
            add(threshold);
        }});
        return lists;
    }

}
